package com.lh.api.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.lh.api.config.MyConstants;
import com.lh.api.dao.*;
import com.lh.api.form.AddExpressForm;
import com.lh.api.form.AfterSaleForm;
import com.lh.api.form.RefundForm;
import com.lh.api.service.OrderAfterSaleService;
import com.lh.api.service.OrderService;
import com.lh.api.vo.*;
import com.lh.common.entity.admin.*;
import com.lh.common.entity.state.RemarkEnum;
import com.lh.common.entity.state.STATE;
import com.lh.common.enums.*;
import com.lh.common.utils.*;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.annotation.After;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Gze
 * @ClassName: OrderAfterSaleServiceImpl
 * @Description: (类作用)
 * @date: 2020-05-21 10:27
 */
@Service
public class OrderAfterSaleServiceImpl extends ServiceImpl<OrderAfterSaleMapper, OrderAfterSale> implements OrderAfterSaleService {

    @Autowired
    private OrderShopMapper orderShopMapper;

    @Autowired
    private OrderAfterSaleLogMapper orderAfterSaleLogMapper;

    @Autowired
    private OrderService orderService;

    @Autowired
    private ReasonMapper reasonMapper;

    @Autowired
    private ReturnAddressMapper returnAddressMapper;

    @Override
    @Transactional
    public void createRefund(RefundForm refundForm, Long userId) {
        OrderAfterSale orderRefund = new OrderAfterSale();
        //查询订单是否能退款
        Order order = orderService.selectByItem(refundForm.getOrderItem());
        AssertUtil.assertNotNull(order, Constant.RESULT.FI1000,"Order does not exist!");
        AssertUtil.assertNotTrue(!AfterSaleOrderTypeEnum.NONE.equals(order.getAfterSaleType()), Constant.RESULT.FI1000, "This order has been applied for after sales");

        //支付完成且物流状态为未发货才能申请
        AssertUtil.assertNotTrue( !(OrderStatusEnum.TOSHIP.equals(order.getOrderStatus())), Constant.RESULT.FI1000, "This order cannot be refunded");

        //生成售后单号
        String afterSaleId = KeyGenerator.getAfterSaleOrderID(AfterSaleOrderTypeEnum.TK);

        orderRefund.setAfterSaleId(afterSaleId);
        orderRefund.setOrderItem(order.getOrderItem());
        orderRefund.setType(AfterTypeEnum.REFUND);
        orderRefund.setStatus(AfterStatusEnum.PROCESSING);
        orderRefund.setReason(refundForm.getReason());
        orderRefund.setRemark(refundForm.getRemark());
        orderRefund.setUserId(userId);
        orderRefund.setCreateTime(new Date());
        orderRefund.setUpdateTime(new Date());
        orderRefund.setRefundPrice(order.getPayPrice());
        baseMapper.insert(orderRefund);

        Order updateOrder = new Order();
        updateOrder.setOid(order.getOid());
        updateOrder.setAfterSaleType(AfterSaleOrderTypeEnum.TK);
        orderService.updateBykey(updateOrder);
        //记录日志
        insertLog(afterSaleId, userId, AfterStatusEnum.PROCESSING, AfterStatusEnum.PROCESSING, RemarkEnum.SHZT05);
    }

    @Override
    @Transactional
    public void createAfterSale(AfterSaleForm afterSaleForm, Long userId) {
        AssertUtil.assertNotTrue(afterSaleForm.getProofPics().split(",").length > 5, Constant.RESULT.FI1000, "No more than 5 pictures");

        OrderAfterSale orderAfterSale = new OrderAfterSale();

        //查询订单是否能申请售后
        Order order = orderService.selectByItem(afterSaleForm.getOrderItem());
        AssertUtil.assertNotNull(order, Constant.RESULT.FI1000,"Order does not exist!");
        AssertUtil.assertNotTrue(!AfterSaleOrderTypeEnum.NONE.equals(order.getAfterSaleType()), Constant.RESULT.FI1000, "This order has been applied for after sales");
        AssertUtil.assertNotTrue(!(OrderStatusEnum.COMPLETED.equals(order.getOrderStatus())), Constant.RESULT.FI1000, "This order cannot be refunded");

        if(order.getSignTime() != null){
            AssertUtil.assertNotTrue(System.currentTimeMillis()-order.getSignTime().getTime() > 15*24*60*60*1000, Constant.RESULT.FI1000, "Timeout, unable to apply for return");
        }

        //生成售后单号
        String afterSaleId = KeyGenerator.getAfterSaleOrderID(AfterSaleOrderTypeEnum.SH);

        orderAfterSale.setAfterSaleId(afterSaleId);
        orderAfterSale.setOrderItem(order.getOrderItem());
        orderAfterSale.setType(AfterTypeEnum.RETURN);
        orderAfterSale.setStatus(AfterStatusEnum.RETURNING);
        orderAfterSale.setReason(afterSaleForm.getReason());
        orderAfterSale.setRemark(afterSaleForm.getRemark());
        orderAfterSale.setUserId(userId);
        orderAfterSale.setCreateTime(new Date());
        orderAfterSale.setUpdateTime(new Date());
        orderAfterSale.setProofPics(afterSaleForm.getProofPics());
        orderAfterSale.setRefundPrice(order.getPayPrice());
        baseMapper.insert(orderAfterSale);

        Order updateOrder = new Order();
        updateOrder.setOid(order.getOid());
        updateOrder.setAfterSaleType(AfterSaleOrderTypeEnum.SH);
        orderService.updateBykey(updateOrder);
        //记录日志
        insertLog(afterSaleId, userId, AfterStatusEnum.RETURNING, AfterStatusEnum.RETURNING, RemarkEnum.SHZT06);
    }

    @Override
    public PageUtils<AfterSaleListVo> getList(Map<String, Object> params, Integer pageNum, Integer pageSize) {
        if(pageNum != null && pageSize != null){
            PageHelper.startPage(pageNum, pageSize);
        }
        List<AfterSaleListVo> afterSaleListVos = this.baseMapper.getlist(params);
        for (AfterSaleListVo afterSaleListVo : afterSaleListVos){
            if(StringUtils.isNotEmpty(afterSaleListVo.getProperty())){
                afterSaleListVo.setPropertyList(ShopServiceImpl.parseData(afterSaleListVo.getProperty()));
            }
        }
        return  new PageUtils<>(afterSaleListVos);
    }

    @Override
    public AfterSaleDetailVo getAfterSaleDetail(String afterSaleId, Long userId) {
        AfterSaleDetailVo afterSaleDetailVo = baseMapper.getAfterSaleDetail(afterSaleId, userId);
        if(afterSaleDetailVo == null){
            return new AfterSaleDetailVo();
        }
        if(AfterStatusEnum.TOWAREHOUSE.equals(afterSaleDetailVo.getStatus())){
            if(afterSaleDetailVo.getAgreeTime() !=null){
                afterSaleDetailVo.setRemainingTime((long) DateTimeUtil.getRemainingTime(new Date(afterSaleDetailVo.getAgreeTime().getTime() + 1000*60*60*24*5)));
            }
            afterSaleDetailVo.setIsUpdateExpress(TrueFalseEnum.TRUE);

            if(afterSaleDetailVo.getUserFillTimeFirst()!=null && new Date().getTime() > (afterSaleDetailVo.getUserFillTimeFirst().getTime() + 1000*60*60*24*1)){
                afterSaleDetailVo.setIsUpdateExpress(TrueFalseEnum.FALSE);
            }

            if(afterSaleDetailVo.getUserUpdateExpressTimes() > 2){
                afterSaleDetailVo.setIsUpdateExpress(TrueFalseEnum.FALSE);
            }
        }
        //整理前端显示的售后日志
        List<AfterSaleLogVo> afterSaleLogVoList = getAfterSalelog(afterSaleDetailVo);
        afterSaleDetailVo.setAfterSaleLogVos(afterSaleLogVoList);
        if(!CollectionUtils.isEmpty(afterSaleDetailVo.getShopList())){
            afterSaleDetailVo.setTotalNum(afterSaleDetailVo.getShopList().stream().collect(Collectors.summingInt(OrderShopVo::getNum)));
        }
        return afterSaleDetailVo;
    }

    /**
    　* @description: 整理前端显示的售后日志
    　* @author GaoZien
    　* @date 2020/6/2 0002
    */
    private List<AfterSaleLogVo> getAfterSalelog(AfterSaleDetailVo afterSaleDetailVo) {
        List<AfterSaleLogVo> result = new ArrayList<>();
        //查询原因和地址
        ReturnAddress returnAddress = null;
        if(afterSaleDetailVo.getAddrId() != null){
            returnAddress = returnAddressMapper.selectById(afterSaleDetailVo.getAddrId());
        }
        Reason reason = null;
        if(afterSaleDetailVo.getReasonId() != null){
            reason = reasonMapper.selectById(afterSaleDetailVo.getReasonId());
        }
        //整合数据
        AfterSaleLogVo temp = new AfterSaleLogVo();
        temp.setCreateTime(afterSaleDetailVo.getCreateTime());
        temp.setOperation("Submit application");
        result.add(temp);

        //退款类型
        if(AfterTypeEnum.REFUND.equals(afterSaleDetailVo.getType()) && AfterStatusEnum.REFUNDSUCCESS.equals(afterSaleDetailVo.getStatus())){
                temp = new AfterSaleLogVo();
                temp.setCreateTime(afterSaleDetailVo.getUpdateTime());
                temp.setOperation("Return agreed");
                temp.setRemark("The seller has agreed to refund. We will contact you later.");
                result.add(temp);
                return result;
        }
        //售后类型
        if(afterSaleDetailVo.getAgreeTime() != null && returnAddress != null){
            temp = new AfterSaleLogVo();
            temp.setCreateTime(afterSaleDetailVo.getAgreeTime());
            temp.setOperation("Return agreed");
            temp.setRemark("Please mail your items to this address within 5 working days. Otherwise, the items might be rejected without refund:"+returnAddress.getAddress()+"; Recipient "+returnAddress.getUserName()+", Mobile: "+returnAddress.getUserPhone()+", and please fill out the logistic info");
            result.add(temp);
        }
        if(AfterStatusEnum.REFUSERETURN.equals(afterSaleDetailVo.getStatus()) && reason != null){
            temp = new AfterSaleLogVo();
            temp.setCreateTime(afterSaleDetailVo.getUpdateTime());
            temp.setOperation(Constant.REFUND_FALIED);
            temp.setRemark(reason.getContent());
            result.add(temp);
        }

        if(afterSaleDetailVo.getUserFillTimeFirst() != null){
            temp = new AfterSaleLogVo();
            temp.setCreateTime(afterSaleDetailVo.getUserFillTimeFirst());
            temp.setOperation("Item return");
            temp.setReExpressName(afterSaleDetailVo.getReExpressName());
            temp.setReExpressCode(afterSaleDetailVo.getReExpressCode());
            result.add(temp);
        }

        if(AfterStatusEnum.REFUSEWAREHOUSE.equals(afterSaleDetailVo.getStatus()) && reason != null){
            temp = new AfterSaleLogVo();
            temp.setCreateTime(afterSaleDetailVo.getUpdateTime());
            temp.setOperation(Constant.REFUND_FALIED);
            temp.setRemark(reason.getContent());
            result.add(temp);
        }
        if(AfterStatusEnum.RETURNTIMEOUT.equals(afterSaleDetailVo.getStatus())){
            temp = new AfterSaleLogVo();
            temp.setCreateTime(afterSaleDetailVo.getUpdateTime());
            temp.setOperation(Constant.REFUND_FALIED);
            temp.setRemark("Exceed the time limit");
            result.add(temp);
        }
        if(AfterStatusEnum.RETURNSUCCESS.equals(afterSaleDetailVo.getStatus())){
            temp = new AfterSaleLogVo();
            temp.setCreateTime(afterSaleDetailVo.getUpdateTime());
            temp.setOperation("Refund");
            temp.setRemark("The seller has agreed to refund. We will contact you later.");
            result.add(temp);
        }
        //倒序
        Collections.reverse(result);
        return result;
    }

    @Override
    public void fillLogistics(AddExpressForm addExpressForm, Long userId) {
        QueryWrapper<OrderAfterSale> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("after_sale_id", addExpressForm.getAfterSaleId()).eq("user_id", userId);
        OrderAfterSale orderAfterSale = baseMapper.selectOne(queryWrapper);

        AssertUtil.assertNotNull(orderAfterSale, Constant.RESULT.FI1000, "afterSaleId is invalid");

        // 判断订单状态是否能够填写物流
        AssertUtil.assertNotTrue(!AfterStatusEnum.TOWAREHOUSE.equals(orderAfterSale.getStatus()),Constant.RESULT.FI1004, "This order is not in return, cannot be filled in");

        // 判断订单物流填写是否超过2天
        AssertUtil.assertNotTrue(orderAfterSale.getAgreeTime() != null && System.currentTimeMillis()-orderAfterSale.getAgreeTime().getTime() > 5*24*60*60*1000,
                Constant.RESULT.FI1004, "Timeout, unable to fill in");

        // 判断首次填写是否超过1天
        AssertUtil.assertNotTrue(orderAfterSale.getUserFillTimeFirst() !=null && System.currentTimeMillis()-orderAfterSale.getUserFillTimeFirst().getTime() > 24*60*60*1000,
                Constant.RESULT.FI1004, "You can only modify it in one day");
        //   判断订单物流是否更新过2次
        AssertUtil.assertNotTrue(orderAfterSale.getUserUpdateExpressTimes()>=2,Constant.RESULT.FI1004, "It has been modified twice and can't be modified any more");

        OrderAfterSale orderAfterSaleUp =  new OrderAfterSale();
        orderAfterSaleUp.setId(orderAfterSale.getId());
        orderAfterSaleUp.setReExpressName(addExpressForm.getExpressName());
        orderAfterSaleUp.setReExpressCode(addExpressForm.getExpressCode());
        orderAfterSaleUp.setUpdateTime(new Date());
        //判断是否首次填写，首次填写则需更新user_fill_time_first
        if(orderAfterSale.getUserFillTimeFirst() == null && orderAfterSale.getReExpressCode() == null){
            orderAfterSaleUp.setUserFillTimeFirst(new Date());
        }else{
            orderAfterSaleUp.setUserUpdateExpressTimes(orderAfterSale.getUserUpdateExpressTimes()+1);
        }
        baseMapper.updateByKey(orderAfterSaleUp);
    }

    @Override
    public void delAfterSale(Long userId, String afterSaleId) {
        QueryWrapper<OrderAfterSale> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("after_sale_id", afterSaleId).eq("user_id", userId);
        OrderAfterSale orderAfterSale = baseMapper.selectOne(queryWrapper);
        if(orderAfterSale == null ){
            return;
        }
        // 判断订单状态是否能够填写物流
        AssertUtil.assertNotTrue(!(AfterStatusEnum.REFUNDSUCCESS.equals(orderAfterSale.getStatus())
                || AfterStatusEnum.RETURNSUCCESS.equals(orderAfterSale.getStatus())
                || AfterStatusEnum.REFUSERETURN.equals(orderAfterSale.getStatus())
                || AfterStatusEnum.REFUSEWAREHOUSE.equals(orderAfterSale.getStatus())
                || AfterStatusEnum.REFUSEREFUND.equals(orderAfterSale.getStatus())),Constant.RESULT.FI1004, "Order in post-sale status cannot be deleted");

        baseMapper.deleteById(orderAfterSale.getId());
    }

    @Override
    public List<ReasonListVo> getReasonList(ReasonEnum reasonType) {
        return reasonMapper.getReasonList(reasonType);
    }

    public void insertLog(String afterSaleId, Long userId, AfterStatusEnum oldStatus, AfterStatusEnum newStatus, String remark) {
        OrderAfterSaleLog orderAfterSaleLog = new OrderAfterSaleLog();
        orderAfterSaleLog.setAfterSaleId(afterSaleId);
        orderAfterSaleLog.setUserId(userId);
        orderAfterSaleLog.setOldStatus(oldStatus);
        orderAfterSaleLog.setNewStatus(newStatus);
        orderAfterSaleLog.setCreateTime(new Date());
        orderAfterSaleLog.setUpdateTime(new Date());
        orderAfterSaleLog.setRemark(remark);
        orderAfterSaleLogMapper.insert(orderAfterSaleLog);
    }
}
